package com.yfbao.encryptor;

import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.yfbao.config.FieldEncrypt;

import java.lang.reflect.Field;
import java.util.function.Predicate;

import com.baomidou.mybatisplus.core.conditions.AbstractLambdaWrapper;
import com.baomidou.mybatisplus.core.conditions.query.Query;
import com.baomidou.mybatisplus.core.toolkit.support.SerializedLambda;
import java.lang.reflect.Method;


/**
 * 支持加密字段查询的Lambda Wrapper
 * 仅支持等于(eq)和不等于(ne)查询
 */
public class EncryptLambdaQueryWrapper<T> extends AbstractLambdaWrapper<T, EncryptLambdaQueryWrapper<T>>
        implements Query<EncryptLambdaQueryWrapper<T>, T, SFunction<T, ?>> {

    private AESEncryptor encryptor;

    public EncryptLambdaQueryWrapper() {
        super();
    }

    public EncryptLambdaQueryWrapper(AESEncryptor encryptor) {
        super();
        this.encryptor = encryptor;
    }



    @Override
    protected EncryptLambdaQueryWrapper<T> instance() {
        // 创建新的实例并传递entityClass和encryptor
        EncryptLambdaQueryWrapper<T> wrapper = new EncryptLambdaQueryWrapper<>();
        if (this.encryptor != null) {
            wrapper.setEncryptor(this.encryptor);
        }
        return wrapper;
    }

    /**
     * 设置加密器
     */
    public EncryptLambdaQueryWrapper<T> setEncryptor(AESEncryptor encryptor) {
        this.encryptor = encryptor;
        return this;
    }

    /**
     * 等于查询 - 自动处理加密字段
     */
    @Override
    public EncryptLambdaQueryWrapper<T> eq(SFunction<T, ?> column, Object val) {
        if (needEncrypt(column) && val instanceof String) {
            val = encryptor.encrypt((String) val);
        }
        return super.eq(column, val);
    }

    /**
     * 不等于查询 - 自动处理加密字段
     */
    @Override
    public EncryptLambdaQueryWrapper<T> ne(SFunction<T, ?> column, Object val) {
        if (needEncrypt(column) && val instanceof String) {
            val = encryptor.encrypt((String) val);
        }
        return super.ne(column, val);
    }

    /**
     * 判断字段是否需要加密
     */
    private boolean needEncrypt(SFunction<T, ?> column) {
        if (encryptor == null || getEntityClass() == null) {
            return false;
        }

        try {
            String fieldName = getFieldName(column);
            Field field = getField(getEntityClass(), fieldName);
            return field != null && field.isAnnotationPresent(FieldEncrypt.class);
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 获取实体类 - 从父类获取
     */
    public Class<T> getEntityClass() {
        try {
            // 尝试从当前实例获取entityClass字段（优先使用实例而非类）
            Class<?> clazz = this.getClass();
            while (clazz != null && clazz != Object.class) {
                try {
                    Field entityClassField = clazz.getDeclaredField("entityClass");
                    entityClassField.setAccessible(true);
                    Class<T> result = (Class<T>) entityClassField.get(this);
                    if (result != null) {
                        return result;
                    }
                } catch (NoSuchFieldException e) {
                    // 继续向上查找
                }
                clazz = clazz.getSuperclass();
            }
            return null;
        } catch (Exception e) {
            return null;
        }
    }


    /**
     * 获取字段名 - 使用标准的SerializedLambda方式
     */
    private String getFieldName(SFunction<T, ?> lambda) {
        try {
            // 使用SerializedLambda获取方法信息
            Method writeReplace = lambda.getClass().getDeclaredMethod("writeReplace");
            writeReplace.setAccessible(true);
            SerializedLambda serializedLambda = (SerializedLambda) writeReplace.invoke(lambda);

            String methodName = serializedLambda.getImplMethodName();

            // 根据getter方法名推断字段名
            if (methodName.startsWith("get") && methodName.length() > 3) {
                return Character.toLowerCase(methodName.charAt(3)) + methodName.substring(4);
            } else if (methodName.startsWith("is") && methodName.length() > 2) {
                return Character.toLowerCase(methodName.charAt(2)) + methodName.substring(3);
            }
            return methodName;
        } catch (Exception e) {
            throw new RuntimeException("获取字段名失败", e);
        }
    }

    /**
     * 获取字段信息
     */
    private Field getField(Class<T> clazz, String fieldName) {
        while (clazz != null && clazz != Object.class) {
            try {
                Field field = clazz.getDeclaredField(fieldName);
                field.setAccessible(true);
                return field;
            } catch (NoSuchFieldException e) {
                clazz = (Class<T>) clazz.getSuperclass();
            } catch (Exception e) {
                break;
            }
        }
        return null;
    }

    /**
     * 重写toString，显示加密信息
     */
    @Override
    public String toString() {
        return "EncryptLambdaQueryWrapper{encryptor=" + (encryptor != null ? "enabled" : "disabled") + "}";
    }

    @Override
    public EncryptLambdaQueryWrapper<T> select(SFunction<T, ?>... columns) {
        throw new RuntimeException("不支持");
    }

    @Override
    public EncryptLambdaQueryWrapper<T> select(Class<T> entityClass, Predicate<TableFieldInfo> predicate) {
        throw new RuntimeException("不支持");
    }

}

